#include "permUtility.h"
#include <stdio.h>

void printUsage() {
	printf("Usage is:\n");
	printf("\t-i Input List File\n");
	printf("\t-x Index files\n");
	printf("\t-o Output files' prefix (default : temp)\n");
	printf("\t-p Total number of permutations (default: 1e9)\n");
	printf("\t-b Number of blocks used (default: 128)\n");
	printf("\t-d Specify the gpu device id (default : assigned automatically)\n");
	printf("\t--marginal switch test mode to marginal association test (default : association allowing for interaction test)\n");
	printf("Examples : \n");
	printf("\tPERMUTE -i .\\filenamelist.txt -x indexfile -o output -p 1000000\n\n");
}


int main(int argc, char **argv) {
	char* inputListFile = NULL;
	char* indexFile = NULL;
	char* mode = NULL;
	struct KernelParams kernelParams;
	kernelParams.numBlock = -1;
	kernelParams.numThread = -1;
	kernelParams.numPermutation = -1;
	kernelParams.deviceId = -1;
	kernelParams.isMarginal = 0;
	kernelParams.output2screen = 0;
	bool validInptFile = false;
	bool validIndexFile = false;

	char* outputPrefix = "temp";

	printf("\n");
	
	// necessary parameters
	for (int i = 1; i < argc; i++) { 
		if (i + 1 != argc) // Check that we haven't finished parsing already
		{
			// Check for input list file
			if ( strcmp(argv[i],"-i") == 0 ) {
				if ( i+1 != argc ) {
					inputListFile = argv[i+1];
					if ( fopen(inputListFile,"r+") != NULL ) {
						validInptFile = true;
					}
					else {
						printf("Unable to open the file : %s\n\n", inputListFile);
					}
				}
				else {
					printf("No input file\n\n");
				}
			}
			// The index file, for marginal association test or association allowing for interaction. 
			if ( strcmp(argv[i],"-x") == 0 ) {
				if ( i+1 != argc ) {
					indexFile = argv[i+1];
					if ( fopen(indexFile,"r+") != NULL ) {
						validIndexFile = true;
					}
					else {
						printf("Unable to open the file : %s\n\n", indexFile);
					}
				}
				else {
					printf("No index file\n\n");
				}
			}
		}
	}

	if ( !validInptFile ) {
		printUsage();
		exit(0);
	}

	// Parse optional arguments, Skip the first argument which is the program name
	for (int i = 1; i < argc; i++) { 
		if (i + 1 != argc) // Check that we haven't finished parsing already
		{			
			// Parse output prefix
			if (strcmp(argv[i],"-o") == 0 ) {
				if ( i+1 != argc ) {
					outputPrefix = argv[i+1];
				}
				else {
					printf("Unable to parse outputPrefix. Outputs files without prefixs.\n\n");
				}
			}
			if (strcmp(argv[i],"-t") == 0 ) {
				if ( i+1 != argc ) {
					kernelParams.numThread = atoi(argv[i+1]);
				}
				else {
					printf("Unable to parse number of threads. The default setting is used.\n\n");
				}
			}
			if (strcmp(argv[i],"-b") == 0 ) {
				if ( i+1 != argc ) {
					kernelParams.numBlock = atoi(argv[i+1]);
				}
				else {
					printf("Unable to parse number of blocks. The default setting is used.\n\n");
				}
			}
			if (strcmp(argv[i],"-p") == 0 ) {
				if ( i+1 != argc ) {
					kernelParams.numPermutation = atoi(argv[i+1]);
				}
				else {
					printf("Unable to parse number of permutations. The default setting is used.\n\n");
				}
			}
			if (strcmp(argv[i],"-d") == 0 ) {
				if ( i+1 != argc ) {
					kernelParams.deviceId = atoi(argv[i+1]);
				}
				else {
					printf("Device id is not specified. The device will be assigned automatically.\n\n");
				}
			}
			
		}
		// If '--marginal' has been set, permute for marginal association.
		// Otherwise, will permute for interaction.
		if (strcmp(argv[i],"--marginal") == 0 ) {
			kernelParams.isMarginal = 1;
		}
		if (strcmp(argv[i],"--screen") == 0 ) {
			kernelParams.output2screen = 1;
			printf("The permutation procedure will be printed on the screen.\n");
		}
	}

	// Check if GPU avaliable
	if ( meetCUDARequirement() == -1 ) {
		printf("You should update your CUDA driver to version 2.3 or higher\n");
		exit(0);
	}

	FLUSH_STDOUT();
	int code = permGPU(inputListFile, indexFile, outputPrefix, kernelParams);
	if(code != 0) {
		printf("Error in permutation!\n");
	} else {
		printf("Permutation finished!\n");
	}
}